<?php

declare(strict_types=1);

/**
 * This file is part of Hyperf.
 *
 * @link     https://www.hyperf.io
 * @document https://doc.hyperf.io
 * @contact  group@hyperf.io
 * @license  https://github.com/hyperf/hyperf/blob/master/LICENSE
 */
namespace App\Controller;

class GuestbookController extends AbstractController
{
    public function listRecent1()
    {
        $page = intval($this->request->input('page', '1'));
        $page = max(1, min($page, 50));
        $pageSize = 10;
        $service = $this->container->get(\App\Service\Guestbook::class);
        $count = $service->countAll();
        $list = $service->listRecent($page, $pageSize);
        $data = ['count' => $count, 'list' => []];
        foreach ($list as $item) {
            $data['list'][] = ['id' => $item->id, 'username' => $item->username, 'message' => $item->message];
        }
        return $this->response->json(['code' => 0, 'message' => '', 'data' => $data]);
    }

    public function listRecent()
    {
        $page = intval($this->request->input('page', '1'));
        $page = max(1, min($page, 50));
        $pageSize = 10;
        $cacheKey = "guestbook:list:p#{$page}";
        $redis = $this->container->get(\Hyperf\Redis\Redis::class);
        $cacheData = $redis->get($cacheKey);
        // 存在缓存，且未过期，直接返回
        if ($cacheData && isset($cacheData['expire']) && $cacheData['expire'] > time()) {
            return $this->response->json(['code' => 0, 'message' => '', 'data' => $cacheData['data']]);
        }
        $lockKey = $cacheKey.':update_lock';
        $check = $redis->incr($lockKey);
        // 如果已经有其它请求去做更新了，直接返回数据
        if ($check && $check > 1 && $cacheData) {
            return $this->response->json(['code' => 0, 'message' => '', 'data' => $cacheData['data']]);
        }
        // 设置一个过期时间（即缓存更新超时时间）
        $redis->expire($lockKey, 5);

        $service = $this->container->get(\App\Service\Guestbook::class);
        $count = $service->countAll();
        $list = $service->listRecent($page, $pageSize);
        $data = ['count' => $count, 'list' => []];
        foreach ($list as $item) {
            $data['list'][] = ['id' => $item->id, 'username' => $item->username, 'message' => $item->message];
        }
        $cacheData = ['data' => $data, 'expire' => time() + 30];
        // 缓存实际过期时间略高于内置过期时间
        $redis->set($cacheKey, $cacheData, 60);
        return $this->response->json(['code' => 0, 'message' => '', 'data' => $data]);
    }

    public function listRecent3()
    {
        static $_caches = [];

        $page = intval($this->request->input('page', '1'));
        $page = max(1, min($page, 50));
        $pageSize = 10;
        $cacheKey = "guestbook:list:p#{$page}";
        $now = time();
        if ($_caches[$cacheKey] && ($_caches[$cacheKey]['expire'] > $now || $_caches[$cacheKey]['lock'] > $now)) {
            $data = $_caches[$cacheKey]['data'];
            return $this->response->json(['code' => 0, 'message' => '', 'data' => $data]);
        }
        $_caches[$cacheKey]['lock'] = $now + 5;
        $service = $this->container->get(\App\Service\Guestbook::class);
        $count = $service->countAll();
        $list = $service->listRecent($page, $pageSize);
        $data = ['count' => $count, 'list' => []];
        foreach ($list as $item) {
            $data['list'][] = ['id' => $item->id, 'username' => $item->username, 'message' => $item->message];
        }
        $_caches[$cacheKey] = ['expire' => time() + 60, 'data' => $data, 'lock' => 0];
        return $this->response->json(['code' => 0, 'message' => '', 'data' => $data]);
    }

    public function post() {

        $username = trim($this->request->input('username', ''));
        $message = trim($this->request->input('message', ''));
        if (!$username || !$message) {
            return $this->response->json(['code' => 2, 'message' => 'empty content']);
        }
        $service = $this->container->get(\App\Service\Guestbook::class);
        $result = $service->postNew($username, $message);
        if (false == $result) {
            return $this->response->json(['code' => 1, 'message' => 'system error']);
        }
        return $this->response->json(['code' => 0, 'message' => '', 'data' => true]);
    }

}
